package com.xyz.app.shiro;

import com.free.common.vo.ResultModel;
import com.free.ext.logger.FreeLogger;
import com.free.ext.logger.FreeLoggerFactory;
import com.free.utils.crypt.DESCrypt;
import com.xyz.app.exception.EmptyAccountException;
import com.xyz.app.exception.EmptyCapatcharException;
import com.xyz.app.exception.EmptyPasswordException;
import com.xyz.app.exception.InvalidCaptachaException;
import com.xyz.domain.constants.EhCacheConstants;
import com.xyz.domain.constants.SysConstants;
import com.xyz.domain.table.CCustomer;
import com.xyz.service.CustomerService;
import com.xyz.shiro.BasicAuthorizingRealm;
import com.xyz.shiro.CaptchaTokenUserNameToken;
import com.xyz.shiro.exception.InvalidAccntPwdException;
import com.xyz.shiro.exception.InvalidAccountException;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.cache.Cache;
import org.springframework.cache.ehcache.EhCacheCacheManager;

import java.util.function.Function;

public class UserRealm extends BasicAuthorizingRealm {

    CustomerService customerService;
    EhCacheCacheManager ehCacheCacheManager;

    private static final FreeLogger LOGGER = FreeLoggerFactory.getLogger(UserRealm.class);

    public UserRealm(CustomerService customerService, EhCacheCacheManager ehCacheCacheManager){
        this.customerService = customerService;
        this.ehCacheCacheManager = ehCacheCacheManager;

    }

    @Override
    public Function<PrincipalCollection, AuthorizationInfo> getAuthorizationFunc() {
//        return principals->{
//            SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
//            simpleAuthorizationInfo.addRole("");
//            Set<String> permission = new HashSet<>(Arrays.asList(""));
//            simpleAuthorizationInfo.addStringPermissions(permission);
//            return simpleAuthorizationInfo;
//        };
        return null;
    }

    @Override
    public Function<AuthenticationToken, AuthenticationInfo> getAuthenticationFunc() {
        return token->{
            CaptchaTokenUserNameToken captToken = (CaptchaTokenUserNameToken)token;
            LOGGER.info("Captcha登录{}", captToken);
            if(StringUtils.isEmpty(captToken.getCapatcha()) || StringUtils.isEmpty(captToken.getToken())){
                throw new EmptyCapatcharException();
            }

            // TokenCaptcha 缓存
            Cache.ValueWrapper valueWrapper = ehCacheCacheManager.getCache(EhCacheConstants.TokenKaptchaCache).get(captToken.getToken());
            if(valueWrapper != null){
                if(!valueWrapper.get().toString().equals(captToken.getCapatcha())){
                    throw new InvalidCaptachaException();
                }
            }else{
                throw new InvalidCaptachaException();
            }

            if(StringUtils.isEmpty(captToken.getUsername())){
                LOGGER.info("Captcha登录{},请输入账号", captToken);
                throw new EmptyAccountException();
            }

            if(StringUtils.isEmpty(captToken.getPassword().toString())){
                LOGGER.info("Captcha登录{},请输入密码", captToken);
                throw new EmptyPasswordException();
            }

            ResultModel res = null;
            try{
                res = customerService.getUserInfoByLoginName(captToken.getUsername());
            }catch (Exception ex){
                LOGGER.info("Captcha登录{},错误的用户名", captToken);
                throw new InvalidAccountException();
            }
            if(!res.isSuccess()){
                LOGGER.info("Captcha登录{},错误的用户名", captToken);
                throw new InvalidAccountException();
            }
            CCustomer customer = (CCustomer) res.getData();
            String custPassword = DESCrypt.encrypt(String.valueOf(captToken.getPassword()), SysConstants.PASSWORD_ENCRYPT_KEY);
            if(!StringUtils.equalsIgnoreCase(customer.getPassword(),custPassword)){
                LOGGER.info("Captcha登录{},账号或者密码错误", captToken);
                throw new InvalidAccntPwdException();
            }
            ehCacheCacheManager.getCache(EhCacheConstants.TokenCache).put(captToken.getUsername(), customer);
            return new SimpleAuthenticationInfo(customer, customer, "User_Realm");
        };
    }

    @Override
    public Function<AuthenticationToken, Boolean> getSupports() {
        return token->token instanceof CaptchaTokenUserNameToken;
    }

}
